package io.renren.modules.sys.service.impl;

import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import io.renren.common.exception.ErrorCode;
import io.renren.common.exception.RenException;
import io.renren.common.page.PageData;
import io.renren.common.page.PageUtils;
import io.renren.common.utils.ConvertUtils;
import io.renren.common.utils.JsonUtils;
import io.renren.modules.sys.dao.SysParamsDao;
import io.renren.modules.sys.dto.SysParamsDTO;
import io.renren.modules.sys.dto.SysParamsQueryDto;
import io.renren.modules.sys.entity.SysParamsEntity;
import io.renren.modules.sys.redis.SysParamsRedis;
import io.renren.modules.sys.service.SysParamsService;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.lang.reflect.Constructor;
import java.util.Arrays;
import java.util.List;

/**
 * 参数管理
 *
 * @author Mark sunlightcs@gmail.com
 * @since 1.0.0
 */
@Service
@RequiredArgsConstructor(onConstructor = @__(@Autowired))
public class SysParamsServiceImpl extends ServiceImpl<SysParamsDao, SysParamsEntity> implements SysParamsService {

    private final SysParamsRedis sysParamsRedis;

    @Override
    public PageData<SysParamsDTO> page(SysParamsQueryDto queryDto) {
        Page<SysParamsDTO> page = new Page<>(queryDto.getPage(), queryDto.getLimit());
        PageUtils.setOrder(page, queryDto.getOrderField(), queryDto.getOrder());
        queryDto.setParamType(1);
        Page<SysParamsDTO> pageVo = baseMapper.page(page, queryDto);
        return PageUtils.getPageData(pageVo.getRecords(), pageVo.getTotal(), SysParamsDTO.class);
    }

    @Override
    public List<SysParamsDTO> list(SysParamsQueryDto queryDto) {
        queryDto.setParamType(1);
        return baseMapper.page(queryDto);
    }

    @Override
    public SysParamsDTO get(Long id) {
        SysParamsEntity entity = baseMapper.selectById(id);

        return ConvertUtils.sourceToTarget(entity, SysParamsDTO.class);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void save(SysParamsDTO dto) {
        SysParamsEntity entity = ConvertUtils.sourceToTarget(dto, SysParamsEntity.class);
        this.save(entity);

        sysParamsRedis.set(entity.getParamCode(), entity.getParamValue());
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void update(SysParamsDTO dto) {
        SysParamsEntity entity = ConvertUtils.sourceToTarget(dto, SysParamsEntity.class);
        updateById(entity);

        sysParamsRedis.set(entity.getParamCode(), entity.getParamValue());
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void delete(Long[] ids) {
        //删除Redis数据
        List<String> paramCodeList = baseMapper.getParamCodeList(ids);
        String[] paramCodes = paramCodeList.toArray(new String[0]);
        sysParamsRedis.delete(paramCodes);

        //删除
        this.removeBatchByIds(Arrays.asList(ids));
    }

    @Override
    public String getValue(String paramCode) {
        String paramValue = sysParamsRedis.get(paramCode);
        if (paramValue == null) {
            paramValue = baseMapper.getValueByCode(paramCode);

            sysParamsRedis.set(paramCode, paramValue);
        }
        return paramValue;
    }

    @Override
    public <T> T getValueObject(String paramCode, Class<T> clazz) {
        String paramValue = getValue(paramCode);
        if (StrUtil.isNotBlank(paramValue)) {
            return JsonUtils.parseObject(paramValue, clazz);
        }

        try {
            // 获取无参构造函数
            Constructor<T> constructor = clazz.getDeclaredConstructor();
            return constructor.newInstance();
        } catch (Exception e) {
            throw new RenException(ErrorCode.PARAMS_GET_ERROR);
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public int updateValueByCode(String paramCode, String paramValue) {
        int count = baseMapper.updateValueByCode(paramCode, paramValue);
        sysParamsRedis.set(paramCode, paramValue);
        return count;
    }

}